﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oci.Athena.DataSource.Hexin;
using System.IO;
using MathWorks.MATLAB.NET.Arrays;
using System.Collections;

namespace StockForeCast
{
    public class StockForeCastCollection
    {
        List<StockForeCastValue> stocks = new List<StockForeCastValue>();
        public void Add(StockForeCastValue stock)
        {
            stocks.Add(stock);
        }
        public List<StockForeCastValue> TakeTop(int num)
        {
            List<StockForeCastValue> taketop = new List<StockForeCastValue>();
            taketop = stocks
                .Where(e => e.stockname.StartsWith("0") || e.stockname.StartsWith("6"))
                .OrderByDescending(e => e.forevalue)
                .Take(num).ToList();
            return taketop;
        }
        public List<StockForeCastValue> TakeBottom(int num)
        {
            List<StockForeCastValue> taketop = new List<StockForeCastValue>();
            taketop = stocks
                .Where(e => e.stockname.StartsWith("0") || e.stockname.StartsWith("6"))
                 .OrderBy(e => e.forevalue)
                .Take(num).ToList();
            return taketop;
        }
    }
    public class StockForeCastValue
    {
        public string filename = null;
        public string stockname = null;
        public List<D1BarRecord> recs = new List<D1BarRecord>();
        public double foreopen = 0;
        public double foreclose = 0;

        public double maxclose = 1;
        public double minclose = 1;
        public double forevalue = 0;

        private DateTime startdate;
        private double ployfitdate;
        private double[] fitdate;

        public StockForeCastValue(string file, bool realdata, bool openclose)
        {
            filename = file;
            stockname = StockName(file);
            Initialize(file, realdata);
            if (recs.Count > 0)
            {
                ForeOpenClose(openclose);
                maxclose = recs.Where(e => e.Close > 0).Max(e => e.Close);
                minclose = recs.Where(e => e.Close > 0).Min(e => e.Close);
            }
        }
        private string StockName(string file)
        {
            string stockname = null;
            int lastl = file.LastIndexOf(@"\");
            stockname = file.Substring(lastl + 1, file.Length - lastl - 1);
            return stockname;
        }
        private DateTime StartDate()
        {
            return recs.Min(e => e.Date);
        }
        //拟合的数据是 和最小日期的差值？还是最大日期加1呢？
        private double PloyFitDate()
        {
            TimeSpan fita = recs.Max(e => e.Date) - recs.Min(e => e.Date);
            TimeSpan fitb = DateTime.Now.Date - recs.Max(e => e.Date);
            return (double)(fita.Days + fitb.Days);
        }
        private double[] FitDate()
        {
            startdate = StartDate();
            return recs.OrderBy(e => e.Date).Select(e => (double)(e.Date - startdate).Days).ToArray();
        }

        //是否可以考虑最高价最低价
        private void ForeOpenClose(bool openclose)
        {
            fitdate = FitDate();
            double[] X = fitdate;
            double[] Yopen;
            double[] Yclose;

            if (openclose)
            {
                Yopen = recs.OrderBy(e => e.Date).Select(e => e.Open).ToArray();
                Yclose = recs.OrderBy(e => e.Date).Select(e => e.Close).ToArray();
            }
            else
            {
                Yopen = recs.OrderBy(e => e.Date).Select(e => e.Low).ToArray();
                Yclose = recs.OrderBy(e => e.Date).Select(e => e.High).ToArray();
            }

            ployfitdate = PloyFitDate();
            double[] X1 = fitdate;
            ArrayList XXX = new ArrayList(X1);
            XXX.RemoveAt(0);
            XXX.Add(ployfitdate);
            X1 = (double[])XXX.ToArray(typeof(double));

            foreopen = ployfitVal(X, Yopen, X1);
            foreclose = ployfitVal(X, Yclose, X1);
            forevalue = (foreclose - foreopen) / foreopen;
        }

        //binary文件内容写入list容器
        //是否写入实时数据，判断文件的日期是否和当日相等即可
        private void Initialize(string filename, bool realdata)
        {
            if (File.Exists(filename))
            {
                D1BarFile file = new D1BarFile();
                bool flag = false;
                using (FileStream stream = File.OpenRead(filename))
                    flag = D1BarFile.Read(ref file, stream);
                if (flag)
                    if (realdata == false)
                    {
                        foreach (D1BarRecord record in file.RecordList)
                            if (record.Date.Date != DateTime.Now.Date)
                                recs.Add(record);
                    }
                    else
                        foreach (D1BarRecord record in file.RecordList)
                            recs.Add(record);
            }
        }
        //Matlab和Csharp混合编程的方法，利用Matlab运算得出想要的一个单数据
        private double ployfitVal(double[] X, double[] Y, double[] X1)
        {
            myCurveFit.myCurveFitclass mmm = new myCurveFit.myCurveFitclass();
            MWNumericArray mx_x1 = X1;
            MWNumericArray mx_X = X;
            MWNumericArray mx_Y = Y;
            MWNumericArray mx_T = 4;
            MWArray[] mx_B = mmm.mypolyfit(1, mx_X, mx_Y, mx_T);//Matlab函数polyfit拟合
            MWArray[] mx_F = mmm.mypolyval(1, mx_B[0], mx_x1);//Matlab函数polyval预测
            MWNumericArray mx_y1 = (MWNumericArray)mx_F[0];
            double[,] csArray = (double[,])mx_y1.ToArray(MWArrayComponent.Real);
            return csArray[0, csArray.Length - 1];
        }
    }
    public class FilesPathList
    {
        private List<string> readfiles = new List<string>();
        private string strStock = Directory.GetCurrentDirectory() + @"\股票日线推荐.txt";
        private string myStock = @"D:\同花顺软件\同花顺\79399379146\StockBlock.ini";
        private string[] dirs1 = Directory.GetFiles(@"D:\同花顺软件\同花顺\history\sznse\day", "*.day");
        private string[] dirs2 = Directory.GetFiles(@"D:\同花顺软件\同花顺\history\shase\day", "*.day");

        public FilesPathList()
        {
            readfiles = readfilepath();
        }

        private void FileDeleteLast(string myfile)
        {
            var lines = System.IO.File.ReadAllLines(myfile);
            System.IO.File.WriteAllLines(myfile, lines.Take(lines.Length - 1).ToArray());
        }

        public List<string> readfilepath()
        {
            List<string> readfilepath = new List<string>();
            foreach (string s in dirs1)
                readfilepath.Add(s);
            foreach (string s in dirs2)
                readfilepath.Add(s);
            return readfilepath;
        }

        public void Run(int num, bool realdata, bool openclose)
        {
            StockForeCastCollection stocks = new StockForeCastCollection();
            foreach (string file in readfiles)
            {
                StockForeCastValue stock = new StockForeCastValue(file, realdata, openclose);
                stocks.Add(stock);
            }

            StockNameTable snt = new StockNameTable();

            StreamWriter sw = File.AppendText(strStock);
            sw.WriteLine();
            sw.WriteLine(DateTime.Now);

            //FileDeleteLast(myStock);
            if (File.Exists(myStock))
                File.Delete(myStock);
            StreamWriter mySW = File.CreateText(myStock);

            string mydefinestock = "[ConfigInfo]" + "\r\n";
            mydefinestock += "ConfigName=stockblock_同花顺方案" + "\r\n";
            mydefinestock += "\r\n";
            mydefinestock += "[BLOCK_STOCK_CONTEXT]" + "\r\n";
            mySW.Write(mydefinestock);
            mySW.WriteLine();
            mySW.Write("21=");

            List<StockForeCastValue> stocknames = stocks.TakeTop(num);
            foreach (StockForeCastValue s in stocknames)
            {
                if (!s.stockname.StartsWith("6"))
                    mySW.Write("33:" + s.stockname.Substring(0, 6) + ",");
                else
                    mySW.Write("17:" + s.stockname.Substring(0, 6) + ",");

                sw.Write("||" + s.stockname);
                sw.Write("||" + snt.stocknum2stockname(s.stockname));
                sw.WriteLine("||预计涨幅：" + s.forevalue);
                Console.WriteLine(s.stockname);
            }

            //mySW.Write("17:000000,");

            //List<StockForeCastValue> stocknamesb = stocks.TakeBottom(10);
            //foreach (StockForeCastValue s in stocknamesb)
            //{

            //    if (s.stockname.IndexOf("6") == -1)
            //        mySW.Write("33:" + s.stockname.Substring(0, 6) + ",");
            //    else
            //        mySW.Write("17:" + s.stockname.Substring(0, 6) + ",");

            //    sw.Write("||" + s.stockname);
            //    sw.Write("||" + snt.stocknum2stockname(s.stockname));
            //    sw.WriteLine("||预计涨幅：" + s.forevalue);
            //    Console.WriteLine(s.stockname);
            //}

            mySW.Flush();
            mySW.Close();
            sw.Flush();
            sw.Close();
        }

    }

    public class StockNameTable
    {
        public Dictionary<string, string> stockname = new Dictionary<string, string>();
        private string stocknametable = @"D:\同花顺软件\同花顺\stocknametable.txt";
        public StockNameTable()
        {
            readfile(stocknametable);
        }
        private void readfile(string file)
        {
            FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
            StreamReader m_streamReader = new StreamReader(fs, Encoding.Default);
            m_streamReader.BaseStream.Seek(0, SeekOrigin.Begin);
            string strLine = m_streamReader.ReadLine();
            while (strLine != null)
            {
                strLine = m_streamReader.ReadLine();
                if (strLine != null)
                    stockname.Add(strLine.Substring(0, 6), strLine.Substring(6, strLine.Length - 6));
            }
        }
        public string stocknum2stockname(string stocknum)
        {
            string temp = stocknum.Substring(0, 6);
            if (stockname.ContainsKey(temp)) return stockname[temp];
            else return temp;
        }
    }
}
